package com.guyu.common.core.util;


import cn.hutool.core.util.StrUtil;
import com.guyu.common.core.entity.KeyValue;
import com.guyu.common.core.enums.able.IEnum;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 枚举工具类<br/>
 * 需要结合IEnum,操作的枚举均需要实现IEnum
 */
public class GuyuEnumUtils {

    /**
     * 查找到得枚举对象, 如果查不到将返回null
     */
    public static <E extends IEnum> E findByName(String name, Class<E> enumClass) {
        if (Objects.isNull(enumClass)) {
            return null;
        }
        if (StrUtil.isBlank(name)) {
            return null;
        }
        for (E enumeration : enumClass.getEnumConstants()) {
            if (enumeration.name().equals(name)) {
                return enumeration;
            }
        }
        return null;
    }

    /**
     * 查找到得枚举对象, 如果查不到将返回默认值
     */
    public static <E extends IEnum> E findByNameToDefault(String name, Class<E> enumClass) {
        E e = findByName(name, enumClass);
        if (Objects.isNull(e)) {
            return getDefault(enumClass);
        }
        return e;
    }

    /**
     * 查找到得枚举对象, 如果查不到将返回null
     */
    public static <E extends IEnum> E findByCode(Integer code, Class<E> enumClass) {
        if (Objects.isNull(enumClass)) {
            return null;
        }
        if (Objects.isNull(code)) {
            return null;
        }
        for (E enumeration : enumClass.getEnumConstants()) {
            if (enumeration.getCode().equals(code)) {
                return enumeration;
            }
        }
        return null;
    }

    /**
     * 查找到得枚举对象, 如果查不到将返回默认值
     */
    public static <E extends IEnum> E findByCodeToDefault(Integer code, Class<E> enumClass) {
        E e = findByCode(code, enumClass);
        if (Objects.isNull(e)) {
            return getDefault(enumClass);
        }
        return e;
    }


    /**
     * 查找到得枚举对象, 如果查不到将返回null
     */
    public static <E extends IEnum> E findByText(String desc, Class<E> enumClass) {
        if (Objects.isNull(enumClass)) {
            return null;
        }
        if (StrUtil.isBlank(desc)) {
            return null;
        }
        for (E enumeration : enumClass.getEnumConstants()) {
            if (enumeration.getDesc().equals(desc)) {
                return enumeration;
            }
        }
        return null;
    }

    /**
     * 查找到得枚举对象, 如果查不到将返回默认值
     */
    public static <E extends IEnum> E findByTextToDefault(String desc, Class<E> enumClass) {
        E e = findByText(desc, enumClass);
        if (Objects.isNull(e)) {
            return getDefault(enumClass);
        }
        return e;
    }

    /**
     * 获取默认枚举
     */
    public static <E extends IEnum> E getDefault(Class<E> enumClass) {
        if (Objects.isNull(enumClass)) {
            return null;
        }
        for (E enumeration : enumClass.getEnumConstants()) {
            if (null != enumeration) {
                return (E) enumeration.getDefault();
            }
        }
        return null;
    }


    /**
     * 获取枚举所有的code列表
     */
    public static <E extends IEnum> List<Integer> allEnumCodes(Class<E> enumClass) {
        if (Objects.isNull(enumClass)) {
            return new ArrayList<>();
        }
        return Stream.of(enumClass.getEnumConstants()).map(IEnum::getCode).collect(Collectors.toList());
    }

    /**
     * 获取枚举所有的描述列表
     */
    public static <E extends IEnum> List<String> allEnumDesc(Class<E> enumClass) {
        if (Objects.isNull(enumClass)) {
            return new ArrayList<>();
        }
        return Stream.of(enumClass.getEnumConstants()).map(IEnum::getDesc).collect(Collectors.toList());
    }

    /**
     * 获取枚举列表 [key-value]
     */
    public static <E extends IEnum> List<KeyValue<Integer, String>> allEnumList(Class<E> enumClass) {
        if (Objects.isNull(enumClass)) {
            return null;
        }
        return Stream.of(enumClass.getEnumConstants()).map(KeyValue::of).collect(Collectors.toList());
    }


    /**
     * 获取枚举 [key-value]
     */
    public static <E extends IEnum> KeyValue<Integer, String> getEnumKeyValue(Integer code, Class<E> enumClass) {
        E byCodeWithoutDefault = findByCode(code, enumClass);
        return KeyValue.of(byCodeWithoutDefault);
    }

    /**
     * 判断code值是否在枚举中
     */
    public static <E extends IEnum> boolean contain(Integer code, Class<E> enumClass) {
        if (Objects.isNull(enumClass) || Objects.isNull(code)) {
            return false;
        }
        for (E enumeration : enumClass.getEnumConstants()) {
            if (enumeration.getCode().equals(code)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断给定的code值列表是否在枚举中
     */
    public static <E extends IEnum> boolean containAllCode(List<Integer> codes, Class<E> enumClass) {
        if (codes == null || codes.size() == 0 || Objects.isNull(enumClass)) {
            return false;
        }
        List<Integer> allCodes = Arrays.stream(enumClass.getEnumConstants()).map(IEnum::getCode).collect(Collectors.toList());
        for (Integer code : codes) {
            if (!allCodes.contains(code)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 批量查找到得枚举对象
     */
    public static <E extends IEnum> List<E> listByCode(List<Integer> codes, Class<E> enumClass) {
        if (codes == null || codes.size() == 0) {
            return new ArrayList<>();
        }
        Map<Integer, E> map = Arrays.stream(enumClass.getEnumConstants()).collect(Collectors.toMap(IEnum::getCode, e -> e));
        return codes.stream().map(map::get).collect(Collectors.toList());
    }


    /**
     * 根据code获取desc
     */
    public static <E extends IEnum> String getTextByCode(Integer code, Class<E> enumClass) {
        E e = findByCode(code, enumClass);
        return Objects.isNull(e) ? null : e.getDesc();
    }
}
